package com.moose.operator.web.service.impl.poetry;

import com.moose.operator.common.PageInfo;
import com.moose.operator.common.QueryWrapper;
import com.moose.operator.model.entity.PoetryItem;
import com.moose.operator.model.param.SearchParam;
import com.moose.operator.model.param.poetry.PoetrySearchParam;
import com.moose.operator.web.service.PoetryItemService;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

/**
 * <p>
 * Description:
 * </p>
 *
 * @author taohua
 * @version v1.0.0
 * @date 2020-12-13 21:47:21:47
 * @see com.moose.operator.web.service.impl
 */
@Service
public class PoetryItemServiceImpl implements PoetryItemService {

  @Resource
  private MongoTemplate mongoTemplate;

  @Override public PageInfo<PoetryItem> listPoetry(PoetrySearchParam searchParam) {
    Integer pageNum = searchParam.getPageNum();
    Integer pageSize = searchParam.getPageSize();

    Query query = QueryWrapper.buildPageQuery(pageNum, pageSize);
    Integer tagId = searchParam.getTagId();
    if (null != tagId) {
      query.addCriteria(Criteria.where("tag_arr.id").is(tagId));
    }
    List<PoetryItem> poetryItems = mongoTemplate.find(query, PoetryItem.class);
    poetryItems = poetryItems.parallelStream().map(poetryItem -> {
      String body = poetryItem.getBody();
      if (!StringUtils.isEmpty(body)) {
        poetryItem.setBody(this.processPoetryBody(body));
      }
      return poetryItem;
    }).collect(Collectors.toList());

    Query countQuery = QueryWrapper.buildQuery();
    if (null != tagId) {
      countQuery.addCriteria(Criteria.where("tag_arr.id").is(tagId));
    }
    long totalSize = mongoTemplate.count(countQuery, PoetryItem.class);

    PageInfo<PoetryItem> pageInfo = new PageInfo<>();
    pageInfo.setList(poetryItems);
    pageInfo.setPageNum(pageNum);
    pageInfo.setPageSize(pageSize);
    pageInfo.setTotalSize(totalSize);
    return pageInfo;
  }

  @Override public PageInfo<PoetryItem> listPoetryRanking(SearchParam searchParam) {
    Integer pageNum = searchParam.getPageNum();
    Integer pageSize = searchParam.getPageSize();
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.project(
            "dynasty", "dynasty_id", "ranking_num", "body", "title",
            "author", "author_id", "poetry_id"),
        Aggregation.sort(Sort.Direction.ASC, "ranking_num"),
        QueryWrapper.buildSkipOperation(pageNum, pageSize),
        QueryWrapper.buildLimitOperation(pageSize));

    AggregationResults<Document> aggregate =
        mongoTemplate.aggregate(aggregation, "poetry_ranking", Document.class);

    List<Document> mappedResults = aggregate.getMappedResults();

    List<PoetryItem> poetryItems = mappedResults.stream().map(document -> {
      PoetryItem poetryItem = new PoetryItem();
      poetryItem.setRankingNum(document.getInteger("ranking_num"));
      poetryItem.setDynasty(document.getString("dynasty"));
      poetryItem.setDynastyId(document.getInteger("dynasty_id"));
      poetryItem.setAuthor(document.getString("author"));
      poetryItem.setAuthorId(document.getInteger("author_id"));
      poetryItem.setTitle(document.getString("title"));
      poetryItem.setBody(this.processPoetryBody(document.getString("body")));
      poetryItem.setId(document.getInteger("poetry_id"));
      return poetryItem;
    }).collect(Collectors.toList());

    long totalSize = mongoTemplate.count(QueryWrapper.buildQuery(), "poetry_ranking");
    PageInfo<PoetryItem> pageInfo = new PageInfo<>();
    pageInfo.setList(poetryItems);
    pageInfo.setPageSize(pageSize);
    pageInfo.setTotalSize(totalSize);
    pageInfo.setPageNum(pageNum);
    return pageInfo;
  }

  private String processPoetryBody(String body) {
    int mMaxLength = 150;
    body = body.replaceAll("\\((.+?\\))", "").replaceAll("<[^>]+>", "");
    if (body.length() >= mMaxLength) {
      body = body.substring(0, mMaxLength);
    }
    return body;
  }
}
